perm filename INGF[MF,ALS] blob sn#774307 filedate 1984-10-31 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00003 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	@* GF file format.
C00028 00003	@* Reading the font information.
C00048 ENDMK
C⊗;
@* GF file format.
A ``generic font'' (\.{GF}) file is produced directly by the \MF\ program
and it specifies the bit patterns of the characters that have been drawn.
The term {\sl generic\/} indicates that this file format doesn't match the
conventions of any name-brand manufacturer; but it is easy to convert
\.{GF} files to the special format required by almost all digital
phototypesetting equipment. There's a strong analogy between the \.{DVI}
files written by \TeX\ and the \.{GF} files written by \MF; and, in fact,
the file formats have a lot in common.  While it has been customary to
translate the information contained in the \.{GF} file into the \.{PXL}
format for use by phototypesetting equipment,
we will be using the \.{.GF} files directly.

A \.{GF} file is a stream of 8-bit bytes that may be
regarded as a series of commands in a machine-like language. The first
byte of each command is the operation code, and this code is followed by
zero or more bytes that provide parameters to the command. The parameters
themselves may consist of several consecutive bytes; for example, the
`|boc|' (beginning of character) command has seven parameters, each of
which is four bytes long. Parameters are usually regarded as nonnegative
integers; but four-byte-long parameters can be either positive or
negative, hence they range in value from $-2↑{31}$ to $2↑{31}-1$.
As in \.{TFM} files, numbers that occupy
more than one byte position appear in BigEndian order,
and negative numbers appear in two's complement notation.

A \.{GF} file consists of a ``preamble,'' followed by a sequence of one or
more ``characters,'' followed by a ``postamble.'' The preamble is simply a
|pre| command, with its parameters that introduce the file; this must come
first.  Each ``character'' consists of a |boc| command, followed by any
number of other commands that specify the ``black'' pixels of a character,
followed by an |eoc| command. The characters appear in the order that \MF\
generated them. If we ignore no-op commands (which are allowed between any
two commands in the file), each |eoc| command is immediately followed by a
|boc| command, or by a |post| command; in the latter case, there are no
more characters in the file, and the remaining bytes form the postamble.
Further details about the postamble will be explained later.

Some parameters in \.{GF} commands are ``pointers.'' These are four-byte
quantities that give the location number of some other byte in the file;
the first byte is number~0, then comes number~1, and so on.

@ The \.{GF} format is intended to be both compact and easily interpreted
by a machine. Compactness is achieved by making most of the information
relative instead of absolute. When a \.{GF}-reading program reads the
commands for a character, it keeps track of several quantities: (a)~the current
row number,~|y|; (b)~the current column number,~|x|; and (c)~the current
starting-column number,~|z|. These are 32-bit signed integers, although
most actual font formats produced from \.{GF} files will need to curtail
this vast range because of practical limitations. (\MF\ output will never
allow $\vert x\vert$, $\vert y\vert$, or $\vert z\vert$ to exceed 4095,
but the \.{GF} format tries to be more general.)

How do \.{GF}'s row and column numbers correspond to the conventions
of \TeX\ and \MF? Well, the ``reference point'' of a character, in \TeX's
view, is considered to be at the lower left corner of the pixel in row~0
and column~0. This point is the intersection of the baseline with the left
edge of the type; it corresponds to location $(0,0)$ in \MF\ programs.
Thus the pixel in row~0 and column~0 is \MF's unit square, comprising the
region of the plane whose coordinates both lie between 0 and~1. Negative
values of~|y| correspond to rows of pixels {\sl below\/} the baseline.

Besides |x|, |y|, and |z|, there's also a fourth aspect of the current
state, namely the @!|paint_switch|, which is always either \\{black} or
\\{white}. Each \\{paint} command advances |x| by a specified amount~|d|,
and blackens the intervening pixels if |paint_switch=black|; then
the |paint_switch| changes its state. \.{GF}'s commands are designed so
that |x| will never decrease within a row, and |y| will never increase
within a character; hence there is no way to whiten a pixel that has
been blackened. Rather than using the |paint_switch| parameter directly,
as is done in \.{GFTYPE}, we will find it convenient to store values in a
|paint_val| array, as will be explained in more detail below.

@ Here is a list of all the commands that may appear in a \.{GF} file. Each
command is specified by its symbolic name (e.g., |boc|), its opcode byte
(e.g., 67), and its parameters (if any). The parameters are followed
by a bracketed number telling how many bytes they occupy; for example,
`|d[2]|' means that parameter |d| is two bytes long.

\yskip\hang|paint_0| 0. This is a \\{paint} command with |d=0|; it does
nothing but change the |paint_switch| from \\{black} to \\{white} or vice~versa.

\yskip\hang\\{paint\_1} through \\{paint\_63} (opcodes 1 to 63).
These are \\{paint} commands with |d=1| to~63, defined as follows: If
|paint_switch=black|, blacken |d|~pixels of the current row~|y|,
in columns |x| through |x+d-1| inclusive. Then, in any case,
complement the |paint_switch| and advance |x| by~|d|.

\yskip\hang|paint1| 64 |d[1]|. This is a \\{paint} command with a specified
value of~|d|; \MF\ uses it to paint when |64≤d<256|.

\yskip\hang|@!paint2| 65 |d[2]|. Same as |paint1|, but |d|~can be as high
as~65535.

\yskip\hang|@!paint3| 66 |d[3]|. Same as |paint1|, but |d|~can be as high
as $2↑{24}-1$. \MF\ never needs this command, and it is hard to imagine
anybody making practical use of it; surely a more compact encoding will be
desirable when characters can be this large. But the command is there,
anyway, just in case.

\yskip\hang|boc| 67 |c[4]| |p[4]| |min_x[4]| |max_x[4]| |min_y[4]|
|max_y[4]| |z[4]|. Beginning of a character:  Here |c| is the character
code, and |p| points to the previous |boc| command (if any) for characters
having this code number modulo 256.  (The pointer |p| is |-1| if there was
no prior character with an equivalent code.) All $x$-coordinates of black
pixels in the character that follows will be |≥min_x| and |≤max_x|; all
$y$-coordinates of black pixels will be |≥min_y| and |≤max_y|. Finally,
|z|~is the leftmost potentially black column in row |max_y|; it satisfies
|min_x≤z≤max_x|. When a \.{GF}-reading program sees a |boc|, it can use
|min_x|, |max_x|, |min_y|, and |max_y| to initialize the bounds of an
array. Then it sets |y←max_y|, |paint_switch←black|, and initializes its
|x| and |z| registers to the stated value of~|z|.

\yskip\hang|eoc| 68. End of character: All pixels blackened so far
constitute the pattern for this character. In particular, a completely
blank character might have |eoc| immediately following |boc|.

\yskip\hang|skip1| 69 |m[1]|. Decrease |y| by |m+1|, set |x←z|, and set
|paint_switch←black|. This is a way to produce |m| all-white rows.

\yskip\hang|@!skip2| 70 |m[2]|. Same as |skip1|, but |m| can be as large
as 65535.

\yskip\hang|@!skip3| 71 |m[3]|. Same as |skip1|, but |m| can be as large
as $2↑{24}-1$. \MF\ obviously never needs this command.

\yskip\hang|new_row| 72 |u[4]|. Decrease |y| by 1 and set |z←z+u|; then set
|x←z| and |paint_switch←black|. (It's a general way to finish one row
and begin another.)

\yskip\hang|@!left_z_83| through |@!left_z_1| (opcodes 73 to 155). Same as
|new_row|, with |u=-83| through |-1|, respectively.

\yskip\hang|right_z_0| 156. Same as |skip1| with |m=0| or |new_row| with
|u=0|.

\yskip\hang|@!right_z_1| through |@!right_z_83| (opcodes 157 to 239). Same as
|new_row|, with |u=+1| through |+83|, respectively. \MF\ generates a
|new_row| command only when $\vert u\vert>83$.

\yskip\hang|@!nop| 240. No operation, do nothing. Any number of |nop|'s
may occur between \.{GF} commands, but a |nop| cannot be inserted between
a command and its parameters or between two parameters.

\yskip\hang|xxx1| 241 |k[1]| |x[k]|. This command is undefined in
general; it functions as a $(k+2)$-byte |nop| unless special \.{GF}-reading
programs are being used. \MF\ generates \\{xxx} commands when encountering
a \&{special} string; this occurs in the \.{GF} file only between
characters, after the preamble, and before the postamble. However, \\{xxx}
commands can appear anywhere. It is recommended that |x| be a string
having the form of a keyword followed by possible parameters relevant to
that keyword.

\yskip\hang|@!xxx2| 242 |k[2]| |x[k]|. Like |xxx1|, but |0≤k<65536|.

\yskip\hang|xxx3| 243 |k[3]| |x[k]|. Like |xxx1|, but |0≤k<@t$2↑{24}$@>|.
\MF\ uses this when sending a \&{special} string whose length exceeds~255.

\yskip\hang|@!xxx4| 244 |k[4]| |x[k]|. Like |xxx1|, but |k| can be
ridiculously large; |k| mustn't be negative.

\yskip\hang|yyy| 245 |n[4]|. This command is undefined in general;
it functions as a 5-byte |nop| unless special \.{GF}-reading programs
are being used. \MF\ puts scaled numbers into |yyy|'s, as a
result of \&{numspecial} commands; the intent is to provide numeric
parameters to \\{xxx} commands that immediately precede.

\yskip\hang|char_loc| 246 |c[1]| |v[4]| |w[4]| |p[4]|.
This command will appear only in the postamble, which will be explained shortly.

\yskip\hang|pre| 247 |i[1]| |k[1]| |x[k]|.
Beginning of the preamble; this must come at the very beginning of the
file. Parameter |i| is an identifying number for \.{GF} format, currently
129. The other information is merely commentary; it is not given
special interpretation like \\{xxx} commands are. (Note that \\{xxx}
commands may immediately follow the preamble, before the first |boc|.)

\yskip\hang|post| 248. Beginning of the postamble, see below.

\yskip\hang|post_post| 249. Ending of the postamble, see below.

\yskip\noindent Commands 250--255 are undefined at the present time.

@d gf_id_byte=129 {identifies the kind of \.{GF} files described here}

@ Here are the opcodes \.{GFtoDOVER} actually refers to.

@d paint_0=0 {beginning of the \\{paint} commands}
@d paint1=64 {move right a given number of columns, then
	black${}\swap{}$white}
@d boc=67 {beginning of a character}
@d eoc=68 {end of a character}
@d skip1=69 {skip over blank rows}
@d new_row=72 {move down one row and adjust |z|}
@d right_z_0=156 {base of shorthand |new_row| commands}
@d right_z_1=157 {next shorthand |new_row| command}
@d right_z_83=239 {last shorthand |new_row| command}
@d left_z_83=73 {first shorthand |new_row| command}
@d nop=240 {no operation}
@d xxx1=241 {for \&{special} strings}
@d yyy=245 {for \&{numspecial} numbers}
@d char_loc=246 {character locators in the postamble}
@d pre=247 {preamble}
@d post=248 {postamble beginning}
@d post_post=249 {postamble ending}
@d undefined_commands==250,251,252,253,254,255

@ The last character in a \.{GF} file is followed by `|post|'; this command
introduces the postamble, which summarizes important facts that \MF\ has
accumulated. The postamble has the form
$$\vbox{\halign{\hbox{#\hfil}\cr
	|post| |p[4]| |@!ds[4]| |@!cs[4]| |@!hppp[4]| |@!vppp[4]|
	 |@!min_x[4]| |@!max_x[4]| |@!min_y[4]| |@!max_y[4]|\cr
	$\langle\,$character locators$\,\rangle$\cr
	|post_post| |q[4]| |i[1]| 223's$[{\G}4]$\cr}}$$
Here |p| is a pointer to the byte following the final |eoc| in the file
(or to the byte following the preamble, if there are no characters);
it can be used to locate the beginning of \\{xxx} commands
that might have preceded the postamble. The |ds| and |cs| parameters
give the design size and check sum, respectively, which are exactly the
values put into the header of the \.{TFM} file that \MF\ produces (or
would produce) on this run. Parameters |hppp| and |vppp| are the ratios of
pixels per point, horizontally and vertically, expressed as |scaled| integers
(i.e., multiplied by $2↑{16}$); they can be used to correlate the font
with specific device resolutions, magnifications, and ``at sizes.''  Then
come |min_x|, |max_x|, |min_y|, and |max_y|, which bound the values that |x|
and~|y| assume in all of the characters of this \.{GF} file.

@ Character locators are introduced by |char_loc| commands,
which contain a character residue~|c|, a character device width~|v|,
a character width~|w|, and a pointer~|p|
to the beginning of that character. (If two or more characters have the
same code~|c| modulo 256, only the last will be indicated; the others can be
located by following backpointers. Characters whose codes differ by a
multiple of 256 are assumed to share the same font metric information,
hence the \.{TFM} file contains only residues of character codes modulo~256.
This convention is intended for oriental languages, when there are many
character shapes but few distinct widths.)
@↑oriental characters@>@↑Chinese characters@>@↑Japanese characters@>

The character device width~|v| is the value of \MF's \&{chardw} parameter,
rounded to the nearest integer, i.e., the number of pixels that the font
designer wishes the character to occupy when it is typeset within a word.

The character width~|w| duplicates the information in the \.{TFM} file; it
is a |fix_word| value relative to the design size, and it should be
independent of magnification.

The backpointer |p| points to the character's |boc|, or to the first of
a sequence of consecutive |nop| or \\{xxx} or |yyy| commands that
immediately precede the |boc|, if such commands exist; such ``special''
commands essentially belong to the characters, while the special commands
after the final character belong to the postamble (i.e., to the font
as a whole). This convention about |p| applies also to the backpointers
in |boc| commands, even though it wasn't explained in the description
of~|boc|.

@ The last part of the postamble, following the |post_post| byte that
signifies the end of the character locators, contains |q|, a pointer to the
|post| command that started the postamble.  An identification byte, |i|,
comes next; this currently equals~129, as in the preamble.

The |i| byte is followed by four or more bytes that are all equal to
the decimal number 223 (i.e., @'337 in octal). \MF\ puts out four to seven of
these trailing bytes, until the total length of the file is a multiple of
four bytes, since this works out best on machines that pack four bytes per
word; but any number of 223's is allowed, as long as there are at least four
of them. In effect, 223 is a sort of signature that is added at the very end.
@↑Fuchs, David Raymond@>

This curious way to finish off a \.{GF} file makes it feasible for
\.{GF}-reading programs to find the postamble first, on most computers,
even though \MF\ wants to write the postamble last. Most operating
systems permit random access to individual words or bytes of a file, so
the \.{GF} reader can start at the end and skip backwards over the 223's
until finding the identification byte. Then it can back up four bytes, read
|q|, and move to byte |q| of the file. This byte should, of course,
contain the value 248 (|post|); now the postamble can be read, so the
\.{GF} reader can discover all the information needed for individual characters.

Unfortunately, however, standard \PASCAL\ does not include the ability to
@↑system dependencies@>
access a random position in a file, or even to determine the length of a file.
Almost all systems nowadays provide the necessary capabilities, so \.{GF}
format has been designed to work most efficiently with modern operating systems.
But if \.{GF} files have to be processed under the restrictions of standard
\PASCAL, one can simply read them from front to back. This will
be adequate for most applications. However, the postamble-first approach
would facilitate a program that merges two \.{GF} files, replacing data
from one that is overridden by corresponding data in the other.
@* Reading the font information.
The \.{DVI} file format does not include information about character
widths nor the detailed raster information that we will need. As noted in
the previous section, \.{DVIIMAGEN} gets this information directly from
the (\.{GF}) files.

The task facing \.{DVIIMAGEN} is quite different from that facing
\.{DVItype} which has a comparatively easy task in this regard, since it
needs only a few words of information from each font.  We will follow this
earlier program as much as possible in our use of file names and related
details but our data structure will necessarily be somewhat more
complicated.

When the \..{DVI} file calls for a glyph~|c| of a particular font~|f| we
should be prepared to deal with any one of several situations:
\yskip\hang 1) The glyph may already have been sent to the \.{imPRESS}
file;
\yskip\hang 2) The raster for this glyph may be in the main memory array
and it may need only a minimum of processing before it can be supplied to
the \.{imPRESS} file;
\yskip\hang 3) The glyph may be available in main mamory but there may be
no room for it in the \.{IMAGEN} memory;
\yskip\hang 4) The indicated font may be in memory but the desired glyph
may be missing;
\yskip\hang 5) The indicated font may not have been loaded into memory.
\yskip\hang 6) The font may not be in memory and there may not be enough
room in memory for it;
\yskip\hang 7) The desired font may not be available.


Normally, we can assume that the requested glyphs will, in fact, be
present in the specified file, and so, proceeding on this basis, we will
read and digest the entire \.{.GF} file and store the information into
arrays so all of the glyphs of the file will be available for distribution
to the \.{imPRESS} file as required. We will also have one general array
of pointers to the raster information and we can indicate the case in
which the glyph has already been supplied by changing this pointer value
to zero and the case of a missing glyph by storing a minus one.  In the
interests of speed, we will store the pointers in a two dimentional array
and allow space for 128 glyphs per font,even for those for those fonts
that may not have this many.  Fonts with more than 128 glyphs will be
alloted two adjacent file names so that they can contain up to 256
different glyphs.

Following \.{DVItype} we will assign the symbol |nf| to the current number
of known fonts (that is, fonts in memory).  Each known font has an
internal number |f|, where |0≤f<nf|; the external number of this font,
i.e., its font identification number in the \.{DVI} file, is
|font_num[f]|, and the external name of this font is the string that
occupies positions |font_name[f]| through |font_name[f+1]-1| of the array
|names|. The latter array consists of |ASCII_code| characters, and
|font_name[nf]| is its first unoccupied position.

@d char_width_end(#)==#]
@d char_width(#)==width[width_base[#]+char_width_end
@d invalid_width==@'17777777777
@d max_raster_space==1000000

@<Glob...@>=
@!font_num:array [0..max_fonts] of integer; {external font numbers}
@!font_name:array [0..max_fonts] of 0..name_size; {starting positions
	of external font names}
@!names:array [0..name_size] of ASCII_code; {characters of names}
@!font_check_sum:array [0..max_fonts] of integer; {check sums}
@!font_scaled_size:array [0..max_fonts] of integer; {scale factors}
@!font_design_size:array [0..max_fonts] of integer; {design sizes}
@!font_space:array [0..max_fonts] of integer; {boundary between ``small''
	and ``large'' spaces}
@!font_bc:array [0..max_fonts] of integer; {beginning characters in fonts}
@!font_ec:array [0..max_fonts] of integer; {ending characters in fonts}
@!width_base:array [0..max_fonts] of integer; {index into |width| table}
@!width:array [0..max_widths] of integer; {character widths, in \.{DVI} units}
@!nf:0..max_fonts; {the number of known fonts}
@!width_ptr:0..max_widths; {the number of known character widths}
@!point_array:[0..max_fonts,0..max_glyph_no] of integer; {pointers to the location
	of the raster information in font_raster_array}
@!font_raster_array:[0..max_raster_space] of eight_bits; {area reserved for
	raster information stored in bytes}

@ @<Set init...@>=
nf←0; width_ptr←0; font_name[0]←0; font_space[0]←0;
for 1←0 to max_fonts do
  for j←0 to max_glyph_no do point_array[i,j]←-1;

@ It is, of course, a simple matter to print the name of a given font.

@p procedure print_font(@!f:integer); {|f| is an internal font number}
var k:0..name_size; {index into |names|}
begin if f=nf then print('UNDEFINED!')
@.UNDEFINED@>
else	begin for k←font_name[f] to font_name[f+1]-1 do
		print(xchr[names[k]]);
	end;
end;

@ An auxiliary array |in_width| is used to hold the widths as they are
input. The global variable |gf_check_sum| is set to the check sum that
appears in the current \.{GF} file.

@<Glob...@>=
@!in_width:array[0..255] of integer; {\.{GF} width data in \.{DVI} units}
@!gf_check_sum:integer; {check sum found in |gf_file|}

@ Here is a procedure that absorbs the necessary information from a
\.{GF} file, assuming that the file has just been successfully reset
so that we are ready to read its first byte. (A complete description of
\.{GF} file format appears in the documentation of \.{GFtype} and will
not be repeated here.) The procedure does not check the \.{GF} file
for validity, nor does it give explicit information about what is
wrong with a \.{GF} file that proves to be invalid; \.{DVIIMAGEN} 
need not do this, since \.{GF} files are almost always valid,
and since the \.{GFtype} utility program has been specifically designed
to diagnose \.{GF} errors. The procedure simply returns |false| if it
detects anything amiss in the \.{GF} data.

There is a parameter, |z|, which represents the scaling factor being
used to compute the font dimensions; it must be in the range $0<z<2↑{27}$.

@p function in_gf(@!z:integer):boolean; {input \.{GF} data or return |false|}
label 9997, {go here when the format is bad}
	9998,	{go here when the information cannot be loaded}
	9999;	{go here to exit}
var k:integer; {index for loops}
@!lh:integer; {length of the header data, in four-byte words}
@!nw:integer; {number of words in the width table}
@!wp:0..max_widths; {new value of |width_ptr| after successful input}
@!alpha,@!beta:integer; {quantities used in the scaling computation}
begin @<Read past the header data; |goto 9997| if there is a problem@>;
@<Store character-width indices at the end of the |width| table@>;
@<Read and convert the width values, setting up the |in_width| table@>;
@<Move the widths from |in_width| to |width|, and append |pixel_width| values@>;
width_ptr←wp; in_gf←true; goto 9999;
9997: print_ln('---not loaded, GF file is bad');
@.GF file is bad@>
9998: in_gf←false;
9999: end;

@ @<Read past the header...@>=
read_gf_word; lh←b2*256+b3;
read_gf_word; font_bc[nf]←b0*256+b1; font_ec[nf]←b2*256+b3;
if font_ec[nf]<font_bc[nf] then font_bc[nf]←font_ec[nf]+1;
if width_ptr+font_ec[nf]-font_bc[nf]+1>max_widths then
	begin print_ln('---not loaded, DVIIMAGEN needs larger width table');
@.DVIIMAGEN needs larger...@>
		goto 9998;
	end;
wp←width_ptr+font_ec[nf]-font_bc[nf]+1;
read_gf_word; nw←b0*256+b1;
if (nw=0)∨(nw>256) then goto 9997;
for k←1 to 3+lh do
	begin if eof(gf_file) then goto 9997;
	read_gf_word;
	if k=4 then
		if b0<128 then gf_check_sum←((b0*256+b1)*256+b2)*256+b3
		else gf_check_sum←(((b0-256)*256+b1)*256+b2)*256+b3;
	end;

@ @<Store character-width indices...@>=
if wp>0 then for k←width_ptr to wp-1 do
	begin read_gf_word;
	if b0>nw then goto 9997;
	width[k]←b0;
	end;

@ The most important part of |in_gf| is the width computation, which
involves multiplying the relative widths in the \.{GF} file by the
scaling factor in the \.{DVI} file. This fixed-point multiplication
must be done with precisely the same accuracy by all \.{DVI}-reading programs,
in order to validate the assumptions made by \.{DVI}-writing programs
like \TeX82.

Let us therefore summarize what needs to be done. Each width in a \.{GF}
file appears as a four-byte quantity called a |fix_word|.  A |fix_word|
whose respective bytes are $(a,b,c,d)$ represents the number
$$x=\left\{\vcenter{\halign{$#$,\hfil\qquad&if $#$\hfil\cr
b\cdot2↑{-4}+c\cdot2↑{-12}+d\cdot2↑{-20}&a=0;\cr
-16+b\cdot2↑{-4}+c\cdot2↑{-12}+d\cdot2↑{-20}&a=255.\cr}}\right.$$
(No other choices of $a$ are allowed, since the magnitude of a \.{GF}
dimension must be less than 16.)  We want to multiply this quantity by the
integer~|z|, which is known to be less than $2↑{27}$. Let $\alpha=16z$.
If $|z|<2↑{23}$, the individual multiplications $b\cdot z$, $c\cdot z$,
$d\cdot z$ cannot overflow; otherwise we will divide |z| by 2, 4, 8, or
16, to obtain a multiplier less than $2↑{23}$, and we can compensate for
this later. If |z| has thereby been replaced by $|z|↑\prime=|z|/2↑e$, let
$\beta=2↑{4-e}$; we shall compute
$$\lfloor(b+c\cdot2↑{-8}+d\cdot2↑{-16})\,z↑\prime/\beta\rfloor$$ if $a=0$,
or the same quantity minus $\alpha$ if $a=255$.  This calculation must be
done exactly, for the reasons stated above; the following program does the
job in a system-independent way, assuming that arithmetic is exact on
numbers less than $2↑{31}$ in magnitude.

@<Read and convert the width values...@>=
@<Replace |z| by $|z|↑\prime$ and compute $\alpha,\beta$@>;
for k←0 to nw-1 do
	begin read_gf_word;
	in_width[k]←(((((b3*z)div@'400)+(b2*z))div@'400)+(b1*z))div beta;
	if b0>0 then if b0<255 then goto 9997
		else in_width[k]←in_width[k]-alpha;
	end

@ @<Replace |z|...@>=
begin alpha←16*z; beta←16;
while z≥@'40000000 do
	begin z←z div 2; beta←beta div 2;
	end;
end

@ A \.{DVI}-reading program usually works with font files instead of
\.{GF} files, so \.{DVIIMAGEN} is atypical in that respect. Font files
should, however, contain exactly the same character width data that is
found in the corresponding \.{GF}s; check sums are used to help
ensure this. In addition, font files usually also contain the widths of
characters in pixels, since the device-independent character widths of
\.{GF} files are generally not perfect multiples of pixels.

The |pixel_width| array contains this information; when |width[k]| is the
device-independent width of some character in \.{DVI} units, |pixel_width[k]|
is the corresponding width of that character in an actual font.
The macro |char_pixel_width| is set up to be analogous to |char_width|.

@d char_pixel_width(#)==pixel_width[width_base[#]+char_width_end

@<Glob...@>=
@!pixel_width:array[0..max_widths] of integer; {actual character widths,
	in pixels}
@!conv:real; {converts \.{DVI} units to pixels}
@!true_conv:real; {converts unmagnified \.{DVI} units to pixels}
@!numerator,@!denominator:integer; {stated conversion ratio}
@!mag:integer; {magnification factor times 1000}

@ The following code computes pixel widths by simply rounding the \.{GF}
widths to the nearest integer number of pixels, based on the conversion factor
|conv| that converts \.{DVI} units to pixels. However, such a simple
formula will not be valid for all fonts, and it will often give results that
are off by $\pm1$ when a low-resolution font has been carefully
hand-fitted. For example, a font designer often wants to make the letter `m'
a pixel wider or narrower in order to make the font appear more consistent.
\.{DVI}-to-printer programs should therefore input the correct pixel width
information from font files whenever there is a chance that it may differ.
A warning message may also be desirable in the case that at least one character
is found whose pixel width differs from |conv*width| by more than a full pixel.
@↑system dependencies@>

@d pixel_round(#)==round(conv*(#))

@<Move the widths from |in_width| to |width|, and append |pixel_width| values@>=
if in_width[0]≠0 then goto 9997; {the first width should be zero}
width_base[nf]←width_ptr-font_bc[nf];
if wp>0 then for k←width_ptr to wp-1 do
	if width[k]=0 then
		begin width[k]←invalid_width; pixel_width[k]←0;
		end
	else	begin width[k]←in_width[width[k]];
		pixel_width[k]←pixel_round(width[k]);
		end